inline	
classification::classification(const std::string  in_feat_gr_List, const std::string  in_lgocv, const int in_nBins, const std::string in_feat_path)
:feat_gr_List(in_feat_gr_List),lgocv(in_lgocv), nBins(in_nBins), feat_path (in_feat_path)
{
  
}


inline	
void
classification::start()
{
  
  group_list.load(feat_gr_List);
  group_list.print("Printing...");
  size_traData = group_list.n_rows*24*4; // Leaving one group out. 4 videos per group
  size_testData = group_list.n_rows*1*4; // Leaving one group out. 4 videos per group
  
  
  field<mat> loocv_group; 
  loocv_group.load(lgocv);
  
  for (uword it = 0; it<loocv_group.n_rows; it++)
  {
    mat groups =  loocv_group(it,1);
    mat test_group = loocv_group(it,0);
    
    int test_id = test_group(0,0);
    //int test_id = 2;/// CAMBIAR!!!!!!!!!!!!!!!!!!!!!!
    //groups.print("Validation indices");
    //cout << "Validation Group " << test_group(0,0) << endl;
    training(groups);
    validation(test_id);
    //cout << "end.. press a key";
    //getchar();
    //training
    
  }
  
  //cout << labels << endl;
  //cout << "Filas " << trainingData.rows << endl;
  //cout << "Columns " << trainingData.cols << endl;
  //cout << trainingData.row(sample -1) << endl;
  //cout << hist_tmp.t() << endl;
  //cout << "TrainingData = "<< endl << " "  << trainingData << endl << endl;
  //cout << trainingData << endl;
  //getchar();
  
}



  /// Training the SVM
inline 
void
classification::training(mat cross_val_groups)
{
  
  field<vec> fea_group;
  fmat trainingDataArma;
  trainingDataArma.set_size(size_traData,nBins*2); //Concatenating two histograms
  fvec labelsArma;
  labelsArma.set_size(size_traData);
  
  fvec hist_tmp;
  int sample =0;
  
  
  for (uword act=0; act<group_list.n_rows; act++)
  {
    for (uword gr = 0; gr<24 ; gr++) // 24 gropus for training. 1 for validation
    {
      int training_gp =  cross_val_groups(0,gr);
      std::stringstream tmp_ss;
      
      if (training_gp <10)
      {
	tmp_ss << feat_path<< group_list(act)<< "_0" << training_gp;
      }
      else
      {
	tmp_ss << feat_path << group_list(act)<< "_" << training_gp;
      }
      
      fea_group.load(tmp_ss.str());
      
      //cout << "In " << tmp_ss.str() << " there are " << fea_group.n_rows << " videos"<<endl;
      // All groups per action contains at least 4 videos
      for (uword vi =0; vi<4; vi++) 
      {
	hist_tmp =  conv_to<fvec>::from(fea_group(vi));
	
	//hist_tmp = fea_group(vi);
	//hist_tmp.t().print("float Hist");
	//cout << "sample = " << sample << endl;
	//cout << "Number of bins: " << hist_tmp.n_rows << endl;
	//hist_tmp.t().print("float Hist");
	
	trainingDataArma.row(sample) = hist_tmp.t();
	labelsArma(sample) = act + 1; // label = action index
	sample++;
	
	
	//double *mem = hist_tmp.memptr();
	//cv::Mat trainingData(1, 32,  CV_32FC1,hist_tmp.memptr());
	//cout << "TrainingData = "<< endl << " "  << trainingData << endl << endl;
	//cout << trainingData << endl;
	//getchar();
      }
    }
  }
  
  //double *mem = hist_tmp.memptr();
  
  cv::Mat trainingDataTmp(nBins*2, size_traData, CV_32FC1, trainingDataArma.memptr());
  cv::Mat trainingData(trainingDataTmp.t());
  
  cv::Mat labelsTmp(1, size_traData, CV_32FC1, labelsArma.memptr());
  cv::Mat labels(labelsTmp.t());
  
  // Set up SVM's parameters
  CvSVMParams params;
  params.svm_type    = CvSVM::C_SVC;
  params.kernel_type = CvSVM::INTER; //CV_COMP_INTERSECT; //http://docs.opencv.org/modules/imgproc/doc/histograms.html
  //params.gamma = 5; // for poly/rbf/sigmoid
  params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100000, 1e-6);

  //cout << "training..." ;
  SVM.train(trainingData, labels, cv::Mat(), cv::Mat(), params); 
  
  
  //cv::Mat results;
  //SVM.predict(trainingData,results);
  
  //cout << "Training results" << endl;
  //cout << results << endl; // Predicted by SVM
}


inline 
void
classification::validation(int test_group)
{
  ///Testing
  
  field<vec> fea_group;
  fvec hist_tmp;
  fmat testingDataArma;
  testingDataArma.set_size(size_testData,nBins*2);
  
  uvec labelsTest;
  labelsTest.set_size(size_testData);
  
  
  int sample = 0;
  //group_list.print("Listado");
  //getchar();
  
  for (uword act=0; act<group_list.n_rows; act++)
  {
    std::stringstream tmp_ss;
    
     if (test_group <10)
      {
	tmp_ss << feat_path<< group_list(act)<< "_0" << test_group;
      }
      else
      {
	tmp_ss << feat_path << group_list(act)<< "_" << test_group;
      }
      
    
    fea_group.load(tmp_ss.str());
    
    //cout << "In " << tmp_ss.str() << " there are " << fea_group.n_rows << " videos"<<endl;
    // All groups per action contains at least 4 videos
    for (uword vi = 0; vi < 4; vi++) 
    {
      hist_tmp =  conv_to<fvec>::from(fea_group(vi));
      
      //hist_tmp = fea_group(vi);
      //hist_tmp.t().print("float Hist");
      //cout << "sample = " << sample << endl;
      testingDataArma.row(sample) = hist_tmp.t();
      labelsTest(sample) = act + 1; // label = action index
      sample++;
      //double *mem = hist_tmp.memptr();
      //cv::Mat trainingData(1, 32,  CV_32FC1,hist_tmp.memptr());
      //cout << "TrainingData = "<< endl << " "  << trainingData << endl << endl;
      //cout << trainingData << endl;
      //getchar();
    }
  }
  
  cv::Mat testingDataTmp(nBins*2, size_testData, CV_32FC1, testingDataArma.memptr());
  cv::Mat testingData(testingDataTmp.t());
  
  //cout << "testing...";

  cv::Mat results;
  SVM.predict(testingData,results);
  //SVM.predict(trainingData,results);

  
  //cout << "Results" << endl;
  //cout << labelsTest.t() << endl;
  //cout << results << endl; // Predicted by SVM
  
  //verificando
  int acc = 0;
  for (uword ver = 0; ver < size_testData; ver++)
  {
    //cout << results.at<float>(ver,0) << endl;
    //cout << labelsTest (ver)<< endl;
    
    float obt = results.at<float>(ver,0);
    float est = labelsTest(ver);
    
    if (obt == est)
    {
      //cout << "iguales: " << endl;
      acc++;
    }
   }
   //cout << acc << " samples well recognised out of " << size_testData << endl;
   //cout << "performance: " << acc*100/size_testData << " %" << endl;
   cout << acc*100/size_testData << " %" << endl;
    
    
  
}
//Taken from: http://dragonwood-blastevil.blogspot.com.au/2013/04/armadillo-to-other-data-format.html
//   cout << "**************" << endl;
//   
//   arma::fvec arma2matData = arma::randu<arma::fvec>(5);
  //   std::cout << "arma2matData: " << std::endl << arma2matData << std::endl;
  //   
  //   cv::Mat cvMatConvTmp(1, 5,  CV_32FC1, arma2matData.memptr());
  //   cv::Mat cvMatConv(cvMatConvTmp.t());
  //   std::cout << "cvMatConv: " << std::endl << cvMatConv << std::endl;
  
  
  